#!/usr/bin/env python
#
#Copyright 2011 Velin Georgiev
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

''' Main application file: "webapp/main.py"- handles events related to the /index.html. '''

__author__ = 'Velin Georgiev'

import os
import re
#Setting up a higher version of django
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from google.appengine.dist import use_library
use_library('django', '1.2')

from google.appengine.api import memcache, users
from google.appengine.ext import db, webapp
from google.appengine.ext.webapp.template import render
from google.appengine.ext.webapp.util import run_wsgi_app
from django.utils import feedgenerator
from datamodel import tbl_posts, tbl_comments
		
class HomePageHandler(webapp.RequestHandler):		
    def get(self):
		strTitlesList = ""
		qrySinglePost = ""
		qrySinglePostId = ""
		qryCommentsList = ""
		comment_id = ""
		categories = ""
		user = users.get_current_user()
		posts = memcache.get('posts')
		#Get the titles list
		selected_category = self.request.get('cat')
		if selected_category != "" and selected_category != "All":
			posts = db.Query(tbl_posts).filter('visible =', True).filter('category =', selected_category).order('-date')
		else:
			posts = db.Query(tbl_posts).filter('visible =', True).order('-date')
		memcache.add('posts', posts)
		#Get categories
		if selected_category == "": selected_category = "All"
		for item in posts:
			strTitlesList = strTitlesList + ('&#167; <a href="/?id=%d&amp;cat=%s">%s</a><br/><br/>' % (item.key().id(), selected_category.replace(" ","+"), item.title))
		if not categories:
			categories = tbl_posts().select_distinct_category()
			memcache.add('categories', categories)
		if self.request.get('id'):
			qrySinglePost = tbl_posts().get_by_id(long(self.request.get('id')))
			#Check if the item exist or is it set to visible
			if (not qrySinglePost) or qrySinglePost.visible == False:
				error_message = "This item no longer exist."
				context = {'error':error_message}
				tmpl = os.path.join(os.path.dirname(__file__), 'templates','error.html')
				self.response.out.write(render(tmpl, context))
				return
			qrySinglePostId = qrySinglePost.key().id()
		if self.request.get('id'):	
			qryCommentsList = db.Query(tbl_comments).filter('post_id =', long(self.request.get('id'))).filter('visible =', True).order('date')	
			comment_id = self.request.get('comment_id')
		context = {
			'user':      user,
			'login':     users.create_login_url(self.request.uri),
			'logout':    users.create_logout_url(self.request.uri),
			'posts': posts,
			'post_id': qrySinglePost,
			'comments_list': qryCommentsList,
			'categories': categories,
			'titles_list': strTitlesList,
			'article_id': qrySinglePostId,
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'templates','index.html')
		self.response.out.write(render(tmpl, context))
		
class AboutPageHandler(webapp.RequestHandler):		
    def get(self):
		user = users.get_current_user()
		context = {
			'user':      user,
			'login':     users.create_login_url(self.request.uri),
			'logout':    users.create_logout_url(self.request.uri),
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'templates','about.html')
		self.response.out.write(render(tmpl, context))
		
class SubmitComment(webapp.RequestHandler):
    def post(self):
		post_id = self.request.get('post_id')
		comment = self.request.get('comment')
		cat_ = self.request.get('cat_')
		#Simple Validation
		if re.search("\S", comment) is None:
			error_message = "You have forgotten to fill in a mandatory field."
			context = {'error':error_message}
			tmpl = os.path.join(os.path.dirname(__file__), 'templates','error.html')
			self.response.out.write(render(tmpl, context))
			return
		tbl_comments().new_item(post_id, unicode(comment.replace("<", "&lt;").replace(">", "&gt;").replace(" ", "&nbsp;").replace("\x09", "&nbsp;&nbsp;&nbsp;&nbsp;").replace("[code]", "<code class=\"prettyprint linenums\">").replace("[/code]", "</code>").replace("[img]", "<img src=\"").replace("[/img]", "\" />").replace("[quote]","<blockquote>").replace("[/quote]","<blockquote>").replace("[b]","<strong>").replace("[/b]","</strong>").replace("[i]","<i>").replace("[/i]","</i>").replace("[u]","<u>").replace("[/u]","</u>").replace("[i]","<i>").replace("[/i]","</i>")))
		self.redirect('/?id=' + str(post_id))
		
class DeleteComment(webapp.RequestHandler):
    def get(self):
		user = users.get_current_user()
		comment_id = self.request.get('comment_id')
		post_id = self.request.get('id')
		#Simple Validation
		post = tbl_comments().get_by_id(int(comment_id))
		if post.author.nickname == user.nickname:
			tbl_comments().delete_item(int(comment_id))
		self.redirect('/?id=' + str(post_id))
		
class Search(webapp.RequestHandler):
	def get(self):
		user = users.get_current_user()
		search_by = self.request.get('keyword')
		if re.search("\S", search_by) is None:
			self.redirect('/')
			return
		query = tbl_posts().search(str(search_by))
		search_list = ""
		for title, id in query.iteritems():
			search_list = search_list + "&#167; <a href=\"/?id="+unicode(id)+"\" >"+unicode(title)+"</a><br/>"
		context = {
			'search_list':search_list,
			'user':      user,
			'login':     users.create_login_url(self.request.uri),
			'logout':    users.create_logout_url(self.request.uri),
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'templates','search.html')
		self.response.out.write(render(tmpl, context))
		
class GetUserPosts(webapp.RequestHandler):
	def get(self):
		posts_list = ""
		user = users.get_current_user()
		query = tbl_comments().get_user_items()
		if query:
			for obj in query:
				posts = tbl_posts().get_by_id(obj)
				posts_list = posts_list + "&#167; <a href=\"/?id="+unicode(obj)+"\" >"+unicode(posts.title)+"</a><br/>"
		context = {
			'posts_list':posts_list,
			'user':      user,
			'login':     users.create_login_url(self.request.uri),
			'logout':    users.create_logout_url(self.request.uri),
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'templates','user.html')
		self.response.out.write(render(tmpl, context))
		
class Feeds(webapp.RequestHandler):
	def get(self):
		feed_dynamic = db.Query(tbl_posts).filter('visible =', True)
		context = {
			'feed_dynamic':feed_dynamic,
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'feed.xml')
		self.response.out.write(render(tmpl, context))
		
class Robots(webapp.RequestHandler):
	def get(self):
		self.response.out.write(render('robots.txt',''))
		
class Sitemap(webapp.RequestHandler):
	def get(self):
		sitemap_dynamic = db.Query(tbl_posts).filter('visible =', True)
		context = {
			'sitemap_dynamic':sitemap_dynamic,
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'sitemap.xml')
		self.response.out.write(render(tmpl, context))

class NotFoundPageHandler(webapp.RequestHandler):
    def get(self):
		self.error(404)
		user = users.get_current_user()
		error_message = "I am sorry, the file you are looking for has not been found."
		context = {
			'error':error_message,
			'user':      user,
			'login':     users.create_login_url(self.request.uri),
			'logout':    users.create_logout_url(self.request.uri),
		}
		tmpl = os.path.join(os.path.dirname(__file__), 'templates','error.html')
		self.response.out.write(render(tmpl, context))
		
application = webapp.WSGIApplication([
    ( '/', HomePageHandler),
	( '/about', AboutPageHandler),
	( '/search', Search),
	( '/new_comment', SubmitComment),
	( '/user', GetUserPosts),
	( '/del', DeleteComment),
	( '/feed', Feeds),
	( '/robots.txt', Robots),
	( '/sitemap.xml', Sitemap),
	('/.*', NotFoundPageHandler),
	
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()